/**
 * Copyright (c) 2011 Nokia Corporation.
 */

#include <QTimer>
#include <QApplication>
#include <math.h>
#include <QDebug>
#include "mygamewindow.h"
#include "QtOpenGLSpriteBatch.h"



/*!
  Constructor.
  Just zero everything. The initialization is done later at initializeGL
*/
MyGameWindow::MyGameWindow(QWidget *parent /* = 0 */)
    : QGLWidget(parent),
      spriteBatch(0)
{
    setAutoFillBackground( false );
    setAttribute (Qt::WA_OpaquePaintEvent);
    setAttribute( Qt::WA_NoSystemBackground );
    setAttribute( Qt::WA_NativeWindow );
    setAttribute( Qt::WA_PaintOnScreen, true );
    setAttribute( Qt::WA_StyledBackground,false);
    setAutoBufferSwap(false);
    // Startup the timer which will call updateGL as fast as it can.
    QTimer *timer = new QTimer(this);
    QObject::connect(timer, SIGNAL(timeout()), this, SLOT(updateGL()));
    timer->start();
}


/*!
  Destructor.
*/
MyGameWindow::~MyGameWindow()
{

}




void MyGameWindow::initializeGL()
{
    qDebug() << "Initializing gl..";
    spriteBatch = new QtOpenGLSpriteBatch( width(), height(), this );
    glViewport(0,0, width(), height());
    texture = glhelpLoadTexture( ":/graphics/sprite1.png");
}

void MyGameWindow::paintGL()
{

        // update here
    float frameDelta = 0.01f;            // note, calculate this later.
    tester.run( frameDelta );

        // Clear the screen and depthbuffer
    glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glDisable( GL_CULL_FACE );
    glDisable( GL_DEPTH_TEST );
    glDepthMask( GL_FALSE );

        // NOTE: You cannot manuallu change GLES2 state with direct commands between
        // spritebatch begin/end without breaking it.

        // SpriteBatch is still on developement stage and doesn�'t support any
        // other projection than custom: You must provide 4x4 projectionmatrix for
        // it manually.
    if (spriteBatch) {
        spriteBatch->begin();
        tester.draw( spriteBatch, texture );
        spriteBatch->end();
    }

    glFinish();         // ??
    swapBuffers();
}


/*!
  The size of our window has been changed. Set new projectionmatrix..
*/
void MyGameWindow::resizeGL(int w, int h)
{
    GLfloat mproj[16] = {
        1.0f, 0, 0, 0,
        0, (float)w / (float)h, 0, 0,
        0, 0, 0, 0,
        0, 0, 0, 1,
    };
    glViewport(0,0, w,h );
    memcpy( matrixProjection, mproj, sizeof( GLfloat ) * 16 );
    currentWidth = w;
    currentHeight = h;
    spriteBatch->setTargetSize( currentWidth, currentHeight );
    qDebug() << "ResizeGL: " << w << "," << h;
}



/*!
    From GameWindow
    \see GameWindow.cpp
*/
void MyGameWindow::onDestroy()
{
    if (spriteBatch) {
        delete spriteBatch;
        spriteBatch = 0;
    }
    glDeleteTextures(1, &texture );
}



/*!
  Load an image with QImage, convert it to GL's format, create OpenGL texture and
  Return it's handle
*/
GLuint MyGameWindow::glhelpLoadTexture( QString imageFile )
{
    QImage image = QImage( imageFile );
    if (image.width()<1 || image.height()<1) return 0;      // Failed to load the texture
    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    GLuint* pTexData = new GLuint[image.width() * image.height()];
    GLuint* sdata = (GLuint*)image.bits();
    GLuint* tdata = pTexData;

    for (int y=0; y<image.height(); y++)
        for (int x=0; x<image.width(); x++) {
            *tdata = ((*sdata&255) << 16) | (((*sdata>>8)&255) << 8)
                    | (((*sdata>>16)&255) << 0) | (((*sdata>>24)&255) << 24);

            sdata++;
            tdata++;
    };

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0,
                 GL_RGBA, GL_UNSIGNED_BYTE, pTexData);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    delete [] pTexData;
    return texture;
}
